package com.moyun.model.common;

import com.moyun.common.enums.CodeEnum;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;

import java.io.Serializable;

/**
 * 响应数据的实体类
 */
@Slf4j
@Getter
@Setter
public class R<T> implements Serializable {

    private static final long serialVersionUID = 1L;

    /**
     * 响应状态码
     */
    @ApiModelProperty("响应状态码")
    private Integer code;
    /**
     * 提示信息
     */
    @ApiModelProperty("提示信息")
    private String msg;
    /**
     * 响应数据
     */
    @ApiModelProperty("响应数据")
    private T data;

    /**
     * @return 返回 响应状态码 、提示信息
     */
    public static <T> R<T> ok() {
        return new R<>(CodeEnum.SUCCESS);
    }

    /**
     * @param code
     * @param msg
     * @return 返回 系统中未定义的 响应状态码 、 提示信息
     */
    public static <T> R<T> ok(Integer code, String msg) {
        return new R<>(code, msg);
    }

    /**
     * @param codeEnum
     * @return 返回 系统中已定义的 响应状态码 、 提示信息
     */
    public static <T> R<T> ok(CodeEnum codeEnum) {
        return new R<>(codeEnum);
    }

    /**
     * @param code
     * @param msg
     * @param data
     * @return 返回 系统中未定义的 响应状态码 、 提示信息  以及 业务响应数据
     */
    public static <T> R<T> ok(Integer code, String msg, T data) {
        return new R<>(code, msg, data);
    }

    /**
     * @param codeEnum (codeEnum维护 系统中已定义好的 响应状态码 、 提示信息)
     * @param data
     * @return 返回 系统中已定义的 响应状态码 、 提示信息  以及 业务响应数据
     */
    public static <T> R<T> ok(CodeEnum codeEnum, T data) {
        return new R<>(codeEnum, data);
    }

    /**
     * @param data
     * @return 返回 业务响应数据
     */
    public static <T> R<T> ok(T data) {
        return new R<>(CodeEnum.SUCCESS, data);
    }

    /**
     * @return 返回 响应状态码 、提示信息
     */
    public static <T> R<T> error() {
        return new R<>(CodeEnum.FAIL);
    }

    /**
     * @param code
     * @param msg
     * @return 返回 系统中未定义的 响应状态码 、 提示信息
     */
    public static <T> R<T> error(Integer code, String msg) {
        return new R<>(code, msg);
    }

    /**
     * @param codeEnum
     * @return 返回 系统中已定义的 响应状态码 、 提示信息
     */
    public static <T> R<T> error(CodeEnum codeEnum) {
        return new R<>(codeEnum);
    }

    /**
     * @param code
     * @param msg
     * @param data
     * @return 返回 系统中未定义的 响应状态码 、 提示信息  以及 业务响应数据
     */
    public static <T> R<T> error(Integer code, String msg, T data) {
        return new R<>(code, msg, data);
    }

    /**
     * @param codeEnum (codeEnum维护 系统中已定义好的 响应状态码 、 提示信息)
     * @param data
     * @return 返回 系统中已定义的 响应状态码 、 提示信息  以及 业务响应数据
     */
    public static <T> R<T> error(CodeEnum codeEnum, T data) {
        return new R<>(codeEnum, data);
    }

    /**
     * @param data
     * @return 返回 业务响应数据
     */
    public static <T> R<T> error(T data) {
        return new R<>(CodeEnum.FAIL, data);
    }

    /**
     * 定义一个空参构造
     */
    public R() {
    }

    /**
     * 自定义返回结果的构造方法（满参构造）
     *
     * @param code
     * @param msg
     * @param data
     */
    public R(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    /**
     * 放入响应状态码和错误提示信息
     *
     * @param code
     * @param msg
     * @return
     */
    public R(Integer code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    /**
     * 放入响应状态码和请求成功后响应的数据
     *
     * @param code
     * @param data
     */
    public R(Integer code, T data) {
        this.code = code;
        this.data = data;
    }

    /**
     * 当程序发生错误时，直接返回 预定的 错误响应码 和 错误提示信息
     *
     * @param codeEnum
     */
    public R(CodeEnum codeEnum) {
        this.msg = codeEnum.getMsg();
        this.code = codeEnum.getCode();
    }

    /**
     * 当程序发生错误时，直接返回 预定的 错误响应码 和 错误提示信息  和 响应数据
     *
     * @param codeEnum
     */
    public R(CodeEnum codeEnum, T data) {
        this.code = codeEnum.getCode();
        this.msg = codeEnum.getMsg();
        this.data = data;
    }

    /**
     * 当程序发生错误时，直接返回 预定的 错误响应码 和 错误提示信息
     *
     * @param data
     */
    public R(T data) {
        this.setData(data);
    }


}
